<template>
  <view class="x-notification-bar" :style="{ backgroundColor: bgColor }">
    <view
      class="x-notification-bar_content"
      :style="{
        left: scrollLeft + '%',
        transform: 'translateX(' + tranformX + '%)',
      }"
    >
      <template v-if="showContent.length">
        <text
          v-for="(item, index) in showContent"
          :key="index"
          class="x-notification-bar_content-item"
          >{{ item }}</text
        >
      </template>
      <slot v-else></slot>
    </view>
  </view>
</template>
<script lang="ts" setup>
  import { ref, onMounted, computed, onBeforeUnmount } from "vue";
  import type { PropType } from "vue";

  type NotificationType = "info" | "success" | "error";

  const scrollLeft = ref(100);
  const tranformX = ref(0);
  const props = defineProps({
    speed: {
      type: Number,
      default: 20,
    },
    content: {
      type: [Array<String>, String],
    },
    zIndex: {
      type: Number,
      default: 999,
    },
    step: {
      type: Number,
      default: 1,
    },
    type: {
      type: String as PropType<NotificationType>,
      default: "info",
    },
    count: {
      type: Number,
      default: 5,
    }
  });

  const bgColor = computed(() => {
    return `var(--x-notification-${props.type}-bg)`;
  });

  const showContent = computed(() => {
    return Array.isArray(props.content)
      ? props.content
      : props.content
      ? [props.content]
      : [];
  });

  const duration = computed(() => {
    return 1000 / props.speed;
  });

  let timeId;
  onMounted(() => {
    tryToScroll();
  });

  const tryToScroll = () => {
    if (!showContent.value.length) return;
    timeId = setTimeout(() => {
      clearTimeout(timeId);
      timeId = null;
      let nextLeft = scrollLeft.value - props.step;
      if (nextLeft < 0) {
        scrollLeft.value = 100;
      } else {
        scrollLeft.value = nextLeft;
      }
      let nextX = tranformX.value - props.step;
      if (nextX < -100) {
        tranformX.value = 0;
      } else {
        tranformX.value = nextX;
      }
      tryToScroll();
    }, duration.value);
  };

  onBeforeUnmount(() => {
    if (timeId) {
      clearTimeout(timeId);
      timeId = null;
    }
  });
</script>
<style lang="less" scoped>
  .x-notification-bar {
    position: fixed;
    top: 44px; /**顶部栏固定44px，所以空出这个位置 */
    left: 0;
    right: 0;
    z-index: v-bind(zIndex);
    height: fit-content;
    overflow: hidden;
    display: flex;
    align-items: center;

    --x-notification-info-bg: #909399;
    --x-notification-success-bg: #67c23a;
    --x-notification-error-bg: #f56c6c;

    .x-notification-bar_content {
      height: 100%;
      width: fit-content;
      position: relative;
      left: 100%;
      transform: translateX(0);
      transition: all calc(v-bind(duration) - 10) ms linear;
      display: flex;
      color: white;
      flex-wrap: nowrap;

      .x-notification-bar_content-item {
        padding-right: 20px;
        white-space: nowrap;
      }
    }
  }
</style>
